from rest_framework.viewsets import ModelViewSet
from rest_framework.response import Response
from django.conf import settings
from rest_framework.views import APIView
from cmdb.models import Server
from system_config.models import Credential
import os
from rest_framework.parsers import MultiPartParser, FormParser
try:
    from libs.ansible_cicd import AnsibleApi
except Exception as e:
    print("导入Ansible模块错误！")

#记录执行命令
from batch.models import ExecutionRecord
from batch.serializers import ExecutionRecordSerializer
from rest_framework import filters
from django_filters.rest_framework import DjangoFilterBackend


class CommandView(APIView):
    def post(self, request):

        server_ids = request.data.get('server_ids')
        command = request.data.get('command')

        #执行记录
        user = request.user
        note = request.data.get('note')

        # 将脚本写入文件
        with open('/tmp/command.sh', 'w') as f:
            f.write(command)

        ansible = AnsibleApi()

        # 创建一个分组
        ansible.inventory.add_group("webservers")
        for i in server_ids:
            server_obj = Server.objects.get(id=i)
            # ssh_ip、ssh_port、ssh用户名、ssh密码
            ssh_ip = server_obj.ssh_ip
            ssh_port = server_obj.ssh_port
            if server_obj.credential:
                ssh_user = server_obj.credential.username
                if server_obj.credential.auth_mode == 1:
                    ssh_pass = server_obj.credential.password
                    ansible.variable_manager.set_host_variable(host=ssh_ip, varname='ansible_ssh_pass', value=ssh_pass)
                else:
                    ssh_key = server_obj.credential.private_key
                    key_file = "/tmp/.ssh_key"
                    with open(key_file, 'w') as f:
                        f.write(ssh_key)
                    ansible.variable_manager.set_host_variable(host=ssh_ip, varname='ansible_ssh_private_key_file', value=key_file)
            else:
                ssh_user = 'root'
            ansible.variable_manager.set_host_variable(host=ssh_ip, varname='ansible_ssh_port', value=ssh_port)
            ansible.variable_manager.set_host_variable(host=ssh_ip, varname='ansible_ssh_user', value=ssh_user)
            # 向组内添加主机
            ansible.inventory.add_host(host=ssh_ip,group="webservers")
        playbook = os.path.join(settings.BASE_DIR, 'batch/files/command_sh.yaml')
        status = ansible.playbook_run([playbook]) # 返回一个状态码，0是正常，非0是有任务异常
        result = ansible.get_result()

        if status == 0:
            result = result['批量执行命令']
            print(result)
            for task in result:
                if result['success']:
                    for ip in result['success']:
                        info = result['success'][ip]['stdout']
            res = {'code': 200, 'msg': '执行成功！', 'data': info}
        else:
            for task in result:
                if result[task]['failed']:
                    for ip in result[task]['failed']:
                        info = result[task]['failed'][ip]['stderr']
                elif result[task]['unreachable']:
                    for ip in result[task]['unreachable']:
                        info = result[task]['failed'][ip]['msg']
            res = {'code': 500, 'msg': '执行失败！', 'data': info}
        if status == 0:
            status = 1
        else:
            status = 2
        ExecutionRecord.objects.create(
            server_ids=server_ids,
            command=command,
            status=status,
            user=user,
            note=note,
            result=info
        )
        return Response(res)


class ServerUploadView(APIView):
    parser_classes = (MultiPartParser, FormParser)

    def post(self, request):
        print(request.data)
        server_ids = request.data.get('server_ids')
        upload_dir = request.data.get('upload_dir')

        # 获取上传的文件
        file_obj = request.FILES.get('file')
        import os
        current_path = os.path.join(settings.BASE_DIR, 'upload', file_obj.name)
        with open(current_path, 'wb') as f:
            for i in file_obj.chunks():  #循环接受文件块
                f.write(i)

        ansible = AnsibleApi()
        # 将发布配置部分变量传递给playbook使用
        extra_vars = {
            "current_path": current_path,
            'upload_dir': upload_dir,
            'file_name': file_obj.name,
        }
        ansible.variable_manager._extra_vars = extra_vars

        # 创建一个分组
        ansible.inventory.add_group("webservers")
        for i in server_ids:
            server_obj = Server.objects.get(id=i)
            # ssh_ip、ssh_port、ssh用户名、ssh密码
            ssh_ip = server_obj.ssh_ip
            ssh_port = server_obj.ssh_port
            if server_obj.credential:
                ssh_user = server_obj.credential.username
                if server_obj.credential.auth_mode == 1:
                    ssh_pass = server_obj.credential.password
                    ansible.variable_manager.set_host_variable(host=ssh_ip, varname='ansible_ssh_pass', value=ssh_pass)
                else:
                    ssh_key = server_obj.credential.private_key
                    key_file = "/tmp/.ssh_key"
                    with open(key_file, 'w') as f:
                        f.write(ssh_key)
                    ansible.variable_manager.set_host_variable(host=ssh_ip, varname='ansible_ssh_private_key_file', value=key_file)
            else:
                ssh_user = 'root'
            ansible.variable_manager.set_host_variable(host=ssh_ip, varname='ansible_ssh_port', value=ssh_port)
            ansible.variable_manager.set_host_variable(host=ssh_ip, varname='ansible_ssh_user', value=ssh_user)
            # 向组内添加主机
            ansible.inventory.add_host(host=ssh_ip,group="webservers")

        playbook = os.path.join(settings.BASE_DIR, 'batch/files/file_copy.yaml')
        status = ansible.playbook_run([playbook]) # 返回一个状态码，0是正常，非0是有任务异常
        result = ansible.get_result()

        if status == 0:
            result = result['查看文件']
            print(result)
            for task in result:
                if result['success']:
                    for ip in result['success']:
                        info = result['success'][ip]['stdout']
            res = {'code': 200, 'msg': '分发成功！', 'data': info}
        else:
            for task in result:
                if result[task]['failed']:
                    for ip in result[task]['failed']:
                        error = result[task]['failed'][ip]['stderr']
                elif result[task]['unreachable']:
                    for ip in result[task]['unreachable']:
                        error = result[task]['failed'][ip]['msg']
            res = {'code': 500, 'msg': '分发失败！', 'data': error}
        return Response(res)


class ExecutionRecordViewSet(ModelViewSet):
    queryset = ExecutionRecord.objects.all()
    serializer_class = ExecutionRecordSerializer

    filter_backends = [filters.SearchFilter, filters.OrderingFilter, DjangoFilterBackend]
    search_fields = ('command',)
    # filterset_fields = ('status',)  # 指定过滤的字段,与自定义的过滤器不能同时使用


    def destroy(self, request, *args, **kwargs):
        instance = self.get_object()
        self.perform_destroy(instance)
        res = {'code': 200, 'msg': '删除成功'}
        return Response(res)


class CommandEchartView(APIView):

    # 数据格式：
    # X: ['2022-7-11', '2022-7-12', '2022-7-13', '2022-7-14', '2022-7-15', '2022-7-16', '2022-7-16']
    # Y1:  [1, 3, 5, 6, 2, 1, 3]
    # Y2:  [3, 21, 4, 2, 1, 3, 2]

    def get(self, request):
        from datetime import datetime, timedelta
        import pandas as pd

        end = datetime.now()
        start = (end - timedelta(6))
        queryset_obj = ExecutionRecord.objects.filter(
            create_time__range=[start, end])  # 或者大于小于 filter(deal_date__gte=week, deal_date__lte=cur_date)

        # 生成时间序列
        date_range = pd.date_range(start=datetime.strftime(start, "%Y-%m-%d"),
                                   end=datetime.strftime(end, "%Y-%m-%d"))  # datetime时间转为日期

        x_data = []
        y_fail_data = []
        y_success_data = []

        for date in date_range:
            date = datetime.strftime(date, "%Y-%m-%d")
            x_data.append(date)
            y_fail_n = 0
            y_success_n = 0
            for i in queryset_obj:
                date_time = datetime.strftime(i.create_time, "%Y-%m-%d")
                if date == date_time:
                    if i.status == 1:  # 1 成功
                        y_success_n += 1
                    elif i.status == 2:  # 2 失败
                        y_fail_n += 1
            y_fail_data.append(y_fail_n)
            y_success_data.append(y_success_n)

        data = {'y_fail_data': y_fail_data, 'y_success_data': y_success_data, 'x_data': x_data}
        res = {'data': data, 'code': 200, 'msg': '成功'}
        return Response(res)


#批量删除执行命令日志
class DeleteExecutionRecordView(APIView):
    def post(self,request):
        # print(request.data.get('selectrow'))
        #前端传递过来的所选择的id
        ids = request.data.get('selectrow')
        try:
            for i in ids:
                id = i['id']
                ExecutionRecord.objects.get(id=id).delete()
            res = {'code': 200, 'msg': '删除成功'}
            return Response(res)
        except Exception as e:
            res = {'code': 500, 'msg': '%s' %e}
            return Response(res)